#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "mqtt_subscriber.h"
#include "MQTTClient.h"

MQTTClient client;

void default_on_message(const char* topic, const char* payload, int len) {
}

OnMessageCallback* on_message_callback = default_on_message;
void set_on_message_callback(OnMessageCallback* callback) {
    on_message_callback = callback;
}

void delivered(void* context, MQTTClient_deliveryToken dt)
{}

int msgarrvd(void* context, char* topicName, int topicLen, MQTTClient_message* message)
{
    printf("[mqtt_subscriber]Message arrived--topic: %s message: %.*s\n", topicName, message->payloadlen, (char*)message->payload);
    on_message_callback(topicName, (char*)message->payload, message->payloadlen);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

void connlost(void* context, char* cause)
{
    printf("[mqtt_subscriber]Connection lost\n");
    if (cause)
        printf("[mqtt_subscriber]     cause: %s\n", cause);
    exit(EXIT_FAILURE);
}

void mqtt_subscriber_init()
{
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    int rc;

    if ((rc = MQTTClient_create(&client, ADDRESS, CLIENTID,
        MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
    {
        printf("[mqtt_subscriber]Failed to create client, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    if ((rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, delivered)) != MQTTCLIENT_SUCCESS)
    {
        printf("[mqtt_subscriber]Failed to set callbacks, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    conn_opts.username = USERNAME;
    conn_opts.password = PASSWORD;
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;
    printf("[mqtt_subscriber]Connecting to mqtt broker %s\n", ADDRESS);
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        printf("[mqtt_subscriber]Failed to connect, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }

    printf("[mqtt_subscriber]Subscribing to topic %s\n", TOPIC);
    if ((rc = MQTTClient_subscribe(client, TOPIC, QOS)) != MQTTCLIENT_SUCCESS)
    {
        printf("Failed to subscribe, return code %d\n", rc);
        exit(EXIT_FAILURE);
    }
}

void mqtt_subscriber_end() {
    int rc;
    if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
    {
        printf("[mqtt_subscriber]Failed to disconnect, return code %d\n", rc);
    }

    MQTTClient_destroy(&client);
    printf("[mqtt_subscriber]Disconnected.\n");
}
